/* hal_adc.h */
#ifndef __HAL_ADC_H__
#define __HAL_ADC_H__

#include "hal_common.h"

/* ADC_FLAG_xxxx. */
#define ADC_FLAG_WATCHDOG_EVENT   ADC_STS_WD_MASK
#define ADC_FLAG_FIFO_EMPTY       ADC_STS_EMPTY_MASK
#define ADC_FLAG_FIFO_FULL        ADC_STS_FULL_MASK
#define ADC_FLAG_FIFO_OVERRUN     ADC_STS_OVR_MASK
#define ADC_FLAG_END_OF_SEQ       ADC_STS_EOSEQ_MASK
#define ADC_FLAG_END_OF_CONV      ADC_STS_EOC_MASK
#define ADC_FLAG_END_OF_SAMPLING  ADC_STS_EOSMP_MASK
#define ADC_FLAG_POWERUP_READY    ADC_STS_ADRDY_MASK

uint32_t ADC_GetStatusFlags(ADC_Type * base); /* ADC_FLAG_xxxx. */
void ADC_ClearStatusFlags(ADC_Type * base, uint32_t flags); /* ADC_FLAG_xxxx. */
void ADC_EnableInterrupts(ADC_Type * base, uint32_t flags); /* ADC_FLAG_xxxx. */
void ADC_DisableInterrupts(ADC_Type * base, uint32_t flags); /* ADC_FLAG_xxxx. */

void ADC_EnableTemperatureSensor(ADC_Type * base, bool enable);

/* cmds for converter. */
typedef enum
{
    ADC_ConvCmd_Enable = ADC_CTRL_ADEN_MASK, /*!< request to enable the converter with power on. */
    ADC_ConvCmd_Disable = ADC_CTRL_ADDIS_MASK, /*!< request to disable the converter with power off. */
    ADC_ConvCmd_Start = ADC_CTRL_ADSTART_MASK, /*!< request to start the conversion (sequence). */
    ADC_ConvCmd_Stop = ADC_CTRL_ADSTOP_MASK, /*!< request to stop the conversion after the current conversion. */
} ADC_ConvCmd_Type;

void ADC_RequestConvCmd(ADC_Type * base, ADC_ConvCmd_Type cmd);
void ADC_WaitConvCmd(ADC_Type * base, ADC_ConvCmd_Type cmd);

typedef enum
{
    ADC_Resolution_12b = 0u,
    ADC_Resolution_10b = 1u,
    ADC_Resolution_8b = 2u,
    ADC_Resolution_6b = 3u,
} ADC_Resolution_Type;

 typedef enum
 {
     ADC_FifoOverrunMode_KeepOldData = 0u, /*!< FIFO register is preserved with the old data when an overrun is detected. */
     ADC_FifoOverrunMode_KeepNewData = 1u, /*!< The last data is overwritten with the conversion result when an overrun is detected. */
 } ADC_FifoOverrunMode_Type;

 typedef enum
{
    ADC_TriggerMode_Software = 0u,
    ADC_TriggerMode_Hardware = 1u,
} ADC_TriggerMode_Type;
 
 typedef enum
 {
     ADC_SeqScanMode_SingleSeq = 0u,
     ADC_SeqScanMode_Continuous = 1u,
     ADC_SeqScanMode_Discontinuous = 2u,
 } ADC_SeqScanMode_Type;

/* converter & fifo. */
typedef struct
{
    /* converter. */
    ADC_Resolution_Type  Resolution;
    uint32_t ConvClkDiv; /* 4-bit. */
    uint32_t ConvStartupClkCount; /* 8-bit. */
    uint32_t ConvSamplingClkCount; /* 8-bit. */
    
    bool EnableAutoOffMode;
    bool EnableWaitMode;
    
    //ADC_TriggerMode_Type TriggerMode;
    
    /* fifo. */
    uint32_t FifoWatermark; /* 4-bit. */
    bool EnableDma;
    ADC_FifoOverrunMode_Type FifoOverrunMode;
    
} ADC_ConvInit_Type;

void ADC_InitConv(ADC_Type * base, ADC_ConvInit_Type * init);

typedef struct
{
    uint32_t SeqLen; /* The SeqLen is SEQLEN+1, SeqLen > 0. */
    ADC_TriggerMode_Type TriggerMode;
    ADC_SeqScanMode_Type SeqScanMode;
} ADC_ConvSeqConf_Type;

void ADC_SetConvSeqConf(ADC_Type * base, ADC_ConvSeqConf_Type * conf);
void ADC_SetConvSeqSlot(ADC_Type * base, uint32_t slot, uint32_t channel);
uint32_t ADC_GetFifoDataRaw(ADC_Type * base);
void ADC_GetConvValue(uint32_t fifo_data_raw, uint32_t * channel, uint32_t * val);


/* watchdog. */
typedef enum
{
    ADC_ConvWatchdogChannelMode_ForOneChannel = 1u,
    ADC_ConvWatchdogChannelMode_ForAllChannels = 0u,
} ADC_ConvWatchdogChannelMode_Type;

typedef enum
{
    ADC_ConvWatchdogValidRange_Outside = 0u,
    ADC_ConvWatchdogValidRange_Inside = 1u,
} ADC_ConvWatchdogValidRange_Type;

typedef struct
{
    ADC_ConvWatchdogChannelMode_Type ChannelMode;
    uint32_t OneChannelIndex;
    
    ADC_ConvWatchdogValidRange_Type ValidRange;
    
    uint32_t HighLimit;
    uint32_t LowLimit;
} ADC_ConvWatchdogConf_Type;

void ADC_SetConvWatchdogConf(ADC_Type * base, ADC_ConvWatchdogConf_Type * conf);

#endif /* __HAL_ADC_H__ */

